/*
 * Customer_test.cpp
 *
 *  Created on: Jun 22, 2013
 *      Author: amatzlia
 */

#include "Customer.h"
#include "mtmtest.h"
using namespace mtm;

namespace CustomerTest {

void createTest() {
	ASSERT_THROWS(INVALID_ID, Customer(-1));
	ASSERT_THROWS(INVALID_ID, Customer(0));
	ASSERT_THROWS(INVALID_ID, Customer(-1, "name"));
	ASSERT_THROWS(INVALID_ID, Customer(0, "name"));
	ASSERT_EQUALS(getCustomerDescriptionString(1, "name"),
			Customer(1, "name").getDescriptionString());
}

void getStringTest() {
	// check getDescriptionString
	Customer customer(1, "Bob");
	ASSERT_EQUALS(getCustomerDescriptionString(1, "Bob"),
			customer.getDescriptionString());

	// check getReportString
	customer.createNewOrder(10);
	customer.addToOpenOrder(10, Album(20, 10, 1, 1, "title1", "artist1"));
	customer.addToOpenOrder(10, Album(30, 12, 1, 1, "title2", "artist2"));
	customer.payForOpenOrder(10);
	customer.createNewOrder(11);
	customer.addToOpenOrder(11, Album(40, 1, 1, 1, "title3", "artist3"));
	ASSERT_EQUALS(
			getCustomerHeaderString(1, "Bob", 2)
					+ getOrderHeaderString(10, 1, 2, true)
					+ getAlbumMinimalString("title1", "artist1", 1, 10)
					+ getAlbumMinimalString("title2", "artist2", 1, 12)
					+ getOrderHeaderString(11, 1, 1, false)
					+ getAlbumMinimalString("title3", "artist3", 1, 1),
			customer.getReportString());

	// check getRevenueString
	ASSERT_EQUALS(getRevenueFromCustomerString(1, "Bob", 2, 22),
			customer.getRevenueString());
}

void createNewOrderTest() {
	Customer customer(1, "Bob");
	ASSERT_NO_THROW(customer.createNewOrder(10));
	ASSERT_THROWS(CUSTOMER_HAS_OPEN_ORDER, customer.createNewOrder(20));
}

void addAndRemoveFromOpenOrderTest() {
	Customer customer(1, "Bob");
	customer.createNewOrder(11);
	ASSERT_NO_THROW(customer.addToOpenOrder(11, Album(2, 1, 1, 1, "", "")));
	customer.payForOpenOrder(11);
	ASSERT_THROWS(ORDER_WAS_ALREADY_PAID,
			customer.addToOpenOrder(11, Album(1)));
	ASSERT_THROWS(ORDER_WAS_ALREADY_PAID,
			customer.removeFromOpenOrder(11, Album(1)));
	customer.createNewOrder(10);
	ASSERT_THROWS(ORDER_WAS_ALREADY_PAID,
			customer.addToOpenOrder(11, Album(1)));
	ASSERT_THROWS(ORDER_WAS_ALREADY_PAID,
			customer.removeFromOpenOrder(11, Album(1)));
	ASSERT_NO_THROW(customer.addToOpenOrder(10, Album(1, 1, 1, 1, "", "")));
	ASSERT_NO_THROW(customer.addToOpenOrder(10, Album(22, 1, 1, 1, "", "")));
	ASSERT_NO_THROW(customer.addToOpenOrder(10, Album(23, 1, 1, 1, "", "")));
	ASSERT_NO_THROW(customer.addToOpenOrder(10, Album(22, 1, 1, 1, "", "")));
	ASSERT_NO_THROW(customer.removeFromOpenOrder(10, Album(22)));
	ASSERT_NO_THROW(customer.removeFromOpenOrder(10, Album(23)));
	ASSERT_THROWS(ORDER_DOESNT_HAVE_ALBUM,
			customer.removeFromOpenOrder(10, Album(2)));
	ASSERT_EQUALS(
			getCustomerHeaderString(1, "Bob", 1)
					+ getOrderHeaderString(10, 1, 1, false)
					+ getAlbumMinimalString("", "", 1, 1)
					+ getOrderHeaderString(11, 1, 1, true)
					+ getAlbumMinimalString("", "", 1, 1),
			customer.getReportString());
}

void payForOpenOrder() {
	Customer customer(1, "Bob");
	customer.createNewOrder(10);
	customer.addToOpenOrder(10,Album(40,1,1,1,"",""));
	ASSERT_NO_THROW(customer.payForOpenOrder(10));
	ASSERT_THROWS(ORDER_WAS_ALREADY_PAID,customer.payForOpenOrder(10));
	customer.createNewOrder(1);
	ASSERT_THROWS(ORDER_WAS_ALREADY_PAID,customer.payForOpenOrder(10));
	ASSERT_THROWS(ORDER_IS_EMPTY, customer.payForOpenOrder(1));
	customer.addToOpenOrder(1, Album(1, 10, 1, 1, "title", "artist"));
	customer.addToOpenOrder(1, Album(2, 20, 1, 1, "title", "artist"));
	customer.addToOpenOrder(1, Album(3, 30, 1, 1, "title", "artist"));
	List<Album> albumsPaid;
	ASSERT_NO_THROW(albumsPaid = customer.payForOpenOrder(1));
	ASSERT_EQUALS(
			getCustomerHeaderString(1, "Bob", 4)
					+ getOrderHeaderString(1, 1, 3, true)
					+ getAlbumMinimalString("title", "artist", 1, 10)
					+ getAlbumMinimalString("title", "artist", 1, 20)
					+ getAlbumMinimalString("title", "artist", 1, 30)
					+ getOrderHeaderString(10, 1, 1, true)
					+ getAlbumMinimalString("", "", 1, 1),
			customer.getReportString());
	ASSERT_EQUALS(getRevenueFromCustomerString(1, "Bob", 4, 61),
			customer.getRevenueString());
	auto iterator = albumsPaid.begin();
	ASSERT_EQUALS(getAlbumFullString(1,10,1,2,"title","artist"),(*iterator++).getFullString());
	ASSERT_EQUALS(getAlbumFullString(2,20,1,2,"title","artist"),(*iterator++).getFullString());
	ASSERT_EQUALS(getAlbumFullString(3,30,1,2,"title","artist"),(*iterator++).getFullString());
}

void sortByIdTest() {
	set<Customer, Customer::SortById> customers;
	customers.insert(Customer(1));
	customers.insert(Customer(10));
	customers.insert(Customer(2));
	customers.insert(Customer(7));
	int sortedIds[] = { 1, 2, 7, 10 };
	int i = 0;
	for (const Customer& customer : customers) {
		ASSERT_EQUALS(Customer(sortedIds[i++]).getDescriptionString(),
				customer.getDescriptionString());
	}
}

}

/* uncomment to run tests, or copy the relevant code */
//using namespace CustomerTest;
//int main() {
//	RUN_TEST(createTest);
//	RUN_TEST(getStringTest);
//	RUN_TEST(createNewOrderTest);
//	RUN_TEST(addAndRemoveFromOpenOrderTest);
//	RUN_TEST(payForOpenOrder);
//	RUN_TEST(sortByIdTest);
//	return 0;
//}
